
const NES_WIDTH = 256;
const NES_HEIGHT = 240;
const NES_FRAMEBUFFER_SIZE = NES_WIDTH * NES_HEIGHT;


var canvas_ctx, image,display_image;
var framebuffer_u8, framebuffer_u32;

var AUDIO_BUFFERING = 1024;
var SAMPLE_COUNT = 4*1024;
var SAMPLE_MASK = SAMPLE_COUNT - 1;
var audio_ctx;
var audio_samples_L = new Float32Array(SAMPLE_COUNT);
var audio_samples_R = new Float32Array(SAMPLE_COUNT);
var audio_write_cursor = 0, audio_read_cursor = 0;

var animationId = 0;

const SCREEN_WIDTH = 256;
const SCREEN_HEIGHT = 240;
var FRAMEBUFFER_SIZE = SCREEN_WIDTH*SCREEN_HEIGHT;

console.log('hello nes')
var nes = new jsnes.NES({
	onFrame: function(framebuffer_24){
		//console.log('onFrame:')
		for(var i = 0; i < NES_FRAMEBUFFER_SIZE; i++) framebuffer_u32[i] = 0xFF000000 | framebuffer_24[i];

		//image.data.set(framebuffer_u8);
		//canvas_ctx.putImageData(image, 0, 0);
	},
	onStatusUpdate:function(msg){
		console.log(msg)
    },
	onAudioSample: function(l, r){
		const writePos = audio_write_cursor;
		audio_samples_L[writePos] = l;
		audio_samples_R[writePos] = r;
		audio_write_cursor = (writePos + 1) & SAMPLE_MASK;
	},
});

var lastFrameTime = 0;
function onAnimationFrame(timestamp){
	animationId = window.requestAnimationFrame(onAnimationFrame);
	if (timestamp - lastFrameTime >= 16.67) { // 60FPS同步
		nes.frame();
		lastFrameTime = timestamp;
	}
	image.data.set(framebuffer_u8);
	canvas_ctx.putImageData(image, 0, 0);
	
	// 使用选择的算法进行图像放大
	/*
    let upscaledData;
    
    upscaledData = nearestNeighborUpscale(
        framebuffer_u8, 
        NES_WIDTH, 
        NES_HEIGHT, 
        SCREEN_WIDTH, 
        SCREEN_HEIGHT
      );
    
    // 设置高分辨率图像数据
    display_image.data.set(upscaledData);
    canvas_ctx.putImageData(display_image, 0, 0);
    * */
}

function audio_remain(){
	return (audio_write_cursor - audio_read_cursor) & SAMPLE_MASK;
}

function audio_callback(event){
	let dst = event.outputBuffer;
	let len = dst.length;
	
	// Attempt to avoid buffer underruns.
	if (audio_remain() < AUDIO_BUFFERING) {
		return;
	}
	
	let dst_l = dst.getChannelData(0);
	let dst_r = dst.getChannelData(1);
	let lastL = 0, lastR = 0;
	for(let i = 0; i < len; i++){
		let src_idx = (audio_read_cursor + i) & SAMPLE_MASK;
		dst_l[i] = lastL = lastL * 0.8 + audio_samples_L[src_idx] * 0.2;
		dst_r[i] = lastR = lastR * 0.8 + audio_samples_R[src_idx] * 0.2;
	}
	
	audio_read_cursor = (audio_read_cursor + len) & SAMPLE_MASK;
}

function keyboard(callback, event){
	var player = 1;
	switch(event.keyCode){
		case 38: // UP
			callback(player, jsnes.Controller.BUTTON_UP); break;
		case 40: // Down
			callback(player, jsnes.Controller.BUTTON_DOWN); break;
		case 37: // Left
			callback(player, jsnes.Controller.BUTTON_LEFT); break;
		case 39: // Right
			callback(player, jsnes.Controller.BUTTON_RIGHT); break;
		case 65: // 'a' - qwerty, dvorak
		case 81: // 'q' - azerty
			callback(player, jsnes.Controller.BUTTON_A); break;
		case 83: // 's' - qwerty, azerty
		case 79: // 'o' - dvorak
			callback(player, jsnes.Controller.BUTTON_B); break;
		case 9: // Tab
			callback(player, jsnes.Controller.BUTTON_SELECT); break;
		case 13: // Return
			callback(player, jsnes.Controller.BUTTON_START); break;
		default: break;
	}
}

/*
function initAudio() {
	audio_ctx = new window.AudioContext();
	audio_ctx.audioWorklet.addModule('my-processor.js').then(() => {
		const workletNode = new AudioWorkletNode(audio_ctx, 'audio-processor');
		workletNode.connect(audio_ctx.destination);
		audio_ctx.suspend(); // 初始状态为暂停
	});
}
* */

function nes_init(canvas_id){
	console.log('nes_init')
	var canvas = document.getElementById(canvas_id);
	canvas_ctx = canvas.getContext("2d");
	image = canvas_ctx.getImageData(0, 0, NES_WIDTH, NES_HEIGHT);
	
	// 创建高分辨率图像数据
    //display_image = canvas_ctx.getImageData(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
	
	canvas_ctx.fillStyle = "black";
	canvas_ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
	
	// Allocate framebuffer array.
	var buffer = new ArrayBuffer(image.data.length);
	framebuffer_u8 = new Uint8ClampedArray(buffer);
	framebuffer_u32 = new Uint32Array(buffer);

	// Setup audio.
	audio_ctx = new window.AudioContext();
	var script_processor = audio_ctx.createScriptProcessor(AUDIO_BUFFERING, 0, 2);
	script_processor.onaudioprocess = audio_callback;
	script_processor.connect(audio_ctx.destination);
	audio_ctx.suspend(); // 初始状态为暂停
}

// 定义全局变量存储定时器ID
var intervalId = null;
function nes_boot(rom_data){
	console.log('nes_boot 11')
	/*
	try {
		if (intervalId !== null) {
			clearInterval(intervalId);
			intervalId = null;
		}
		nes.loadROM(rom_data);
		const frameTime = 1000 / 60;
		function runFrame() {
			nes.frame();
		}
		// 重新启动新定时器
		intervalId = setInterval(runFrame, frameTime);
	}catch(error){
		console.log(error)
	}*/
	nes.loadROM(rom_data);
	animationId = window.requestAnimationFrame(onAnimationFrame);
}

function nes_load_data(canvas_id, rom_data){
	nes_boot(rom_data);
}

function nes_load_url(canvas_id, path){
	nes_init(canvas_id);
	let romData = window.harmonyBridge.getRomStorageData();
	nes_boot(romData);
	/*
	var req = new XMLHttpRequest();
	req.open("GET", path);
	req.overrideMimeType("text/plain; charset=x-user-defined");
	req.onerror = () => console.log(`Error loading ${path}: ${req.statusText}`);
	
	req.onload = function() {
		if (this.status === 200) {
			console.log('responseText.length:'+this.responseText.length)
		    nes_boot(this.responseText);
		} else if (this.status === 0) {
			// Aborted, so ignore error
		} else {
			req.onerror();
		}
	};
	
	req.send();
	* */

}

function nesStartAudio(start) {

	if(start == 'start'){
		console.log('startAudio')
		let constraints = {
			audio: true
		};
		// 返回的Promise对象
		let promise = navigator.mediaDevices.getUserMedia(constraints);
		// then()异步，调用MediaStream对象作为参数
		promise.then(function(MediaStream) {
			audio_ctx.resume();
		}).catch(function(err) {
			console.info(err.name + ": " + err.message);
		});
		if (!audio_ctx || audio_ctx.state === 'closed') {
			console.log('Setup audio:')
			// Setup audio.
			audio_ctx = new window.AudioContext();
			var script_processor = audio_ctx.createScriptProcessor(AUDIO_BUFFERING, 0, 2);
			script_processor.onaudioprocess = audio_callback;
			script_processor.connect(audio_ctx.destination);
			audio_ctx.suspend(); // 初始状态为暂停
		} else if (audio_ctx.state === 'suspended') {
			console.log('resume')
			audio_ctx.resume();
		}
	}else{
		console.log('stop audio')
		if (audio_ctx) {
			// 断开音频节点连接
			audio_ctx.suspend()
		}
	}

	// 使用audioContext进行音频操作
}

// 图像放大算法
function nearestNeighborUpscale(sourceData, sourceWidth, sourceHeight, targetWidth, targetHeight) {
  const targetData = new Uint8ClampedArray(targetWidth * targetHeight * 4);
  const scaleX = sourceWidth / targetWidth;
  const scaleY = sourceHeight / targetHeight;
  
  for (let y = 0; y < targetHeight; y++) {
    for (let x = 0; x < targetWidth; x++) {
      const sourceX = Math.floor(x * scaleX);
      const sourceY = Math.floor(y * scaleY);
      const sourceIndex = (sourceY * sourceWidth + sourceX) * 4;
      const targetIndex = (y * targetWidth + x) * 4;
      
      targetData[targetIndex] = sourceData[sourceIndex];     // R
      targetData[targetIndex + 1] = sourceData[sourceIndex + 1]; // G
      targetData[targetIndex + 2] = sourceData[sourceIndex + 2]; // B
      targetData[targetIndex + 3] = sourceData[sourceIndex + 3]; // A
    }
  }
  
  return targetData;
}

// 为ArkUI添加的控制接口
function nesButtonDown(button) {
	var player = 1;
	switch(button) {
		case 'UP':
			nes.buttonDown(player, jsnes.Controller.BUTTON_UP); break;
		case 'DOWN':
			nes.buttonDown(player, jsnes.Controller.BUTTON_DOWN); break;
		case 'LEFT':
			nes.buttonDown(player, jsnes.Controller.BUTTON_LEFT); break;
		case 'RIGHT':
			nes.buttonDown(player, jsnes.Controller.BUTTON_RIGHT); break;
		case 'A':
			nes.buttonDown(player, jsnes.Controller.BUTTON_A); break;
		case 'B':
			nes.buttonDown(player, jsnes.Controller.BUTTON_B); break;
		case 'SELECT':
			nes.buttonDown(player, jsnes.Controller.BUTTON_SELECT); break;
		case 'START':
			nes.buttonDown(player, jsnes.Controller.BUTTON_START); break;
	}
}

function nesButtonUp(button) {
	var player = 1;
	switch(button) {
		case 'UP':
			nes.buttonUp(player, jsnes.Controller.BUTTON_UP); break;
		case 'DOWN':
			nes.buttonUp(player, jsnes.Controller.BUTTON_DOWN); break;
		case 'LEFT':
			nes.buttonUp(player, jsnes.Controller.BUTTON_LEFT); break;
		case 'RIGHT':
			nes.buttonUp(player, jsnes.Controller.BUTTON_RIGHT); break;
		case 'A':
			nes.buttonUp(player, jsnes.Controller.BUTTON_A); break;
		case 'B':
			nes.buttonUp(player, jsnes.Controller.BUTTON_B); break;
		case 'SELECT':
			nes.buttonUp(player, jsnes.Controller.BUTTON_SELECT); break;
		case 'START':
			nes.buttonUp(player, jsnes.Controller.BUTTON_START); break;
	}
}

// 暂停/恢复游戏
function nesPause() {
	// 这里可以实现暂停功能
	console.log('Pause game');
}

function nesResume() {
	// 这里可以实现恢复功能
	console.log('Resume game');
}

// 重置游戏
function nesReset() {
	// 重新加载ROM来实现重置
	window.cancelAnimationFrame(animationId);
	nes_load_url("nes-canvas", "test.nes");
	console.log('Reset game');
}

// 加载用户选择的ROM数据
function nesLoadRomData() {
	console.log('尝试加载新的ROM数据');
	let romData = window.harmonyBridge.getRomStorageData();
	try {
		// 直接使用传入的数据加载ROM
		nes_boot(romData);
		console.log('ROM加载成功');
		return true;
	} catch (error) {
		console.error('ROM加载失败:', error);
		return false;
	}
}


// 暴露接口给window对象，以便ArkWeb调用
window.nesButtonDown = nesButtonDown;
window.nesButtonUp = nesButtonUp;
window.nesPause = nesPause;
window.nesResume = nesResume;
window.nesReset = nesReset;
window.nesLoadRomData = nesLoadRomData;
window.nesStartAudio = nesStartAudio;
